/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller.commands;

import controller.Constants;
import model.graphic.locations.FlexibleRelativeLocation;
import model.graphic.locations.VerticalLineLocation;
import model.graphic.objects.Graphical;
import model.graphic.objects.AbstractInPort;
import model.graphic.objects.AbstractOutPort;
import model.graphic.objects.GBoxNode;
import model.graphic.objects.GDispatcherPort;
import model.graphic.objects.GInputPort;
import model.graphic.objects.GNode;
import model.graphic.objects.GOutputPort;
import model.graphic.objects.GTransmitterNode;
import model.graphic.objects.GTriggerPort;
import model.graphic.objects.RectangleGraphical;

/**
 *
 * @author Jelle, modified by Ben
 */
public class RedrawCommand extends BasicCommand {

    private RectangleGraphical node;
    private Constants cons = new Constants();


    public RedrawCommand(Graphical gr) {
        this.node = (RectangleGraphical) gr;
    }

    @Override
    public void execute() {
            if (GNode.class.isAssignableFrom(node.getClass())) {
                int x = 0;
                int aantalins = 0;
                int aantalouts = 0;
                //count the amount of visible inPorts and Outports
                for(Graphical g: gmodel.getAttachedObjects(node, Constants.getInportsString())){
                    if(g.isVisible()){
                        aantalins++;
                    }
                }
                for(Graphical g: gmodel.getAttachedObjects(node, Constants.getOutportsString())){
                    if(g.isVisible()){
                        aantalouts++;
                    }
                }

                int aantalp = Math.max(aantalins, aantalouts);
                x = 20 * aantalp;
                if (x > node.getHeight()) {
                    node.setWidthHeight(node.getWidth(), x);
                }
                x = 0;
                for (Graphical g : gmodel.getAttachedObjects(node, cons.getInportsString())) {
                    AbstractInPort ip = (AbstractInPort) g;
                    if(ip.isVisible()){
                        ip.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(node.getUpperLeft(), -1-ip.getWidth(), x),
                                node.getUpperLeft(), node.getLowerRight()));
                        ip.setLocations(ip.getGraphLocation());
                        x += 20;
                    }
                }
                x = 0;
                for (Graphical g : gmodel.getAttachedObjects(node, cons.getOutportsString())) {
                    AbstractOutPort op = (AbstractOutPort) g;
                    if(op.isVisible()){
                        op.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(node.getLowerRight(), 0, -node.getHeight() + x),
                                node.getUpperLeft(), node.getLowerRight()));
                        op.setLocations(op.getGraphLocation());
                        x += 20;
                    }
                }
            } else if (GBoxNode.class.isAssignableFrom(node.getClass())) {
                int x1 = 20;
                int x2 = 20;
                int upcon = 20;
                int lowcon=20;
                GBoxNode bn = (GBoxNode) node;

                for (GTransmitterNode n : gmodel.getAttachedTransmitterNodes((GBoxNode) bn)) {
                    if (n.isLeft()) {
                        n.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(bn.getUpperLeft(), -10, x1),
                                bn.getUpperLeft(), bn.getLowerRight(), upcon, 0));
                        n.setLocations(n.getGraphLocation());

                        for (Graphical gr : gmodel.getObjects(cons.getAttachmentString())) {
                            castingPort(n, gr);
                        }
                        x1 += 20;
                    } else {
                        n.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(bn.getLowerRight(), 0, -bn.getHeight() + x2),
                                bn.getUpperLeft(), bn.getLowerRight(), upcon, lowcon));

                        n.setLocations(n.getGraphLocation());
                        for (Graphical gr : gmodel.getObjects(cons.getAttachmentString())) {
                            castingPort(n, gr);
                        }
                        x2 += 20;
                    }
                    if (x1 > bn.getHeight() || x2 + 20  > bn.getHeight()) {
                        if (x1 > x2) {
                            bn.setWidthHeight(bn.getWidth(),x1);
                        } else {
                            bn.setWidthHeight(bn.getWidth(),x2+20);
                        }

                    }
                }

            }
            gmodel.setModelChanged();
            gmodel.notifyObservers();
            gview.repaint();
        
    }

    public void castingPort(GTransmitterNode n, Graphical gr) {
        try {
            GOutputPort gop = (GOutputPort) gr;
            if (gop.getBase() == n) {
                gop.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(n.getLowerRight(), 0, -n.getHeight()),
                        n.getUpperLeft(), n.getLowerRight()));
                gop.setLocations(gop.getGraphLocation());
            }
        } catch (Exception ex) {
        }
        try {
            GDispatcherPort gdp = (GDispatcherPort) gr;
            if (gdp.getBase() == n) {
                gdp.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(n.getLowerRight(), 0, -n.getHeight()),
                        n.getUpperLeft(), n.getLowerRight()));
                gdp.setLocations(gdp.getGraphLocation());
            }
        } catch (Exception ex) {
        }
        try {
            GInputPort gip = (GInputPort) gr;
            if (gip.getBase() == n) {
                gip.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(n.getUpperLeft(), -gip.getWidth(), 0),
                        n.getUpperLeft(), n.getLowerRight()));
                gip.setLocations(gip.getGraphLocation());
            }
        } catch (Exception ex) {
        }
        try {
            GTriggerPort gtp = (GTriggerPort) gr;
            if (gtp.getBase() == n) {
                gtp.setLocation(new VerticalLineLocation(new FlexibleRelativeLocation(n.getUpperLeft(), -gtp.getWidth(), 0),
                        n.getUpperLeft(), n.getLowerRight()));
                gtp.setLocations(gtp.getGraphLocation());
            }
        } catch (Exception ex) {
        }
    }
}
